package com.gitee.wsl.security.encrypt.sm4

/**
 * Created by $(USER) on $(DATE)
 */

import com.gitee.wsl.security.Security
import kotlin.io.encoding.Base64

class SM4Utils(
    var secretKey: String = "",
    var iv: String = "",
    var hexString: Boolean = false
){
    fun encryptData_ECB(plainText: String): String {
            val keyBytes: ByteArray?
            if (hexString) {
                keyBytes = secretKey.hexToByteArray()
            } else {
                //keyBytes = secretKey.getBytes();
                keyBytes = secretKey.hexToByteArray()
            }
        return Security.encryptSM4_ECB(plainText.encodeToByteArray(),keyBytes).toHexString()

       /* val ctx: SM4_Context = SM4_Context()
        ctx.isPadding = true
        ctx.mode = SM4.SM4_ENCRYPT

            val sm4 = SM4()
            sm4.sm4_setkey_enc(ctx, keyBytes)
            val encrypted: ByteArray = sm4.sm4_crypt_ecb(ctx, plainText.encodeToByteArray())
            return encrypted.toHexString()*/
    }

    fun decryptData_ECB(cipherText: String): String {
        var cipherText = cipherText

            val encrypted: ByteArray = cipherText.hexToByteArray()
            cipherText = Base64.encode(encrypted)

            //cipherText = new BASE64Encoder().encode(encrypted);
            if (cipherText.trim().isNotEmpty()) {
//                val p: Pattern = Pattern.compile("\\s*|\t|\r|\n")
//                val m: Matcher = p.matcher(cipherText)
//                cipherText = m.replaceAll("")
                cipherText = cipherText.replace("\\s*|\t|\r|\n".toRegex(),"")
            }

            val keyBytes: ByteArray?
            if (hexString) {
                keyBytes = secretKey.hexToByteArray()
            } else {
                keyBytes = secretKey.encodeToByteArray()
            }

        return Security.decryptSM4_ECB(Base64.decode(cipherText),keyBytes).decodeToString()

       /* val ctx: SM4_Context = SM4_Context()
        ctx.isPadding = true
        ctx.mode = SM4.SM4_DECRYPT

            val sm4: SM4 = SM4()
            sm4.sm4_setkey_dec(ctx, keyBytes)
            val decrypted: ByteArray = sm4.sm4_crypt_ecb(ctx, Base64.decode(cipherText))
            //byte[] decrypted = sm4.sm4_crypt_ecb(ctx, new BASE64Decoder().decodeBuffer(cipherText));
            return decrypted.decodeToString()*/
    }

    fun encryptData_CBC(plainText: String): String {
            val keyBytes: ByteArray?
            val ivBytes: ByteArray?
            if (hexString) {
                keyBytes = secretKey.hexToByteArray()
                ivBytes = iv.hexToByteArray()
            } else {
                keyBytes = secretKey.encodeToByteArray()
                ivBytes = iv.encodeToByteArray()
            }

        return Security.encryptSM4_CBC(plainText.encodeToByteArray(),keyBytes,ivBytes).toHexString()

//        val ctx: SM4_Context = SM4_Context()
//        ctx.isPadding = true
//        ctx.mode = SM4.SM4_ENCRYPT
//            val sm4: SM4 = SM4()
//            sm4.sm4_setkey_enc(ctx, keyBytes)
//            val encrypted: ByteArray = sm4.sm4_crypt_cbc(ctx, ivBytes, plainText.encodeToByteArray())
//            return encrypted.toHexString()

    }

    fun decryptData_CBC(cipherText: String): String {
        var cipherText = cipherText
            val encrypted: ByteArray = cipherText.hexToByteArray()
            cipherText = Base64.encode(encrypted)

            //cipherText = new BASE64Encoder().encode(encrypted);
            if (cipherText.trim().isNotEmpty()) {
//                val p: Pattern = Pattern.compile("\\s*|\t|\r|\n")
//                val m: Matcher = p.matcher(cipherText)
//                cipherText = m.replaceAll("")
                cipherText = cipherText.replace("\\s*|\t|\r|\n".toRegex(),"")
            }

            val keyBytes: ByteArray?
            val ivBytes: ByteArray?
            if (hexString) {
                keyBytes = secretKey.hexToByteArray()
                ivBytes = iv.hexToByteArray()
            } else {
                keyBytes = secretKey.encodeToByteArray()
                ivBytes = iv.encodeToByteArray()
            }

        return Security.decryptSM4_CBC(Base64.decode(cipherText),keyBytes,ivBytes).decodeToString()

        /*val ctx: SM4_Context = SM4_Context()
        ctx.isPadding = true
        ctx.mode = SM4.SM4_DECRYPT

        val sm4: SM4 = SM4()
        sm4.sm4_setkey_dec(ctx, keyBytes)
        //byte[] decrypted = sm4.sm4_crypt_cbc(ctx, ivBytes, new BASE64Decoder().decodeBuffer(cipherText));
        val decrypted: ByteArray = sm4.sm4_crypt_cbc(ctx, ivBytes, Base64.decode(cipherText))
        *//*String text = new String(decrypted, "UTF-8");
        return text.substring(0,text.length()-1);*//*
        return decrypted.decodeToString()*/

    }
}

fun Security.encryptSM4_ECB(data:ByteArray,secretKey: ByteArray): ByteArray{
    val ctx = SM4_Context()
    ctx.isPadding = true
    ctx.mode = Sm4Model.SM4_ENCRYPT
    val sm4 = SM4()
    sm4.sm4_setkey_enc(ctx, secretKey)
    val encrypted: ByteArray = sm4.sm4_crypt_ecb(ctx, data)
    return encrypted
}

fun Security.decryptSM4_ECB(cipherData:ByteArray,secretKey: ByteArray,): ByteArray{
    val ctx = SM4_Context()
    ctx.isPadding = true
    ctx.mode = Sm4Model.SM4_DECRYPT
    val sm4: SM4 = SM4()
    sm4.sm4_setkey_dec(ctx, secretKey)
    val decrypted: ByteArray = sm4.sm4_crypt_ecb(ctx, cipherData)
    return decrypted
}

fun Security.encryptSM4_CBC(data:ByteArray,secretKey: ByteArray,iv:ByteArray): ByteArray{
    val ctx = SM4_Context()
    ctx.isPadding = true
    ctx.mode = Sm4Model.SM4_ENCRYPT

    val sm4: SM4 = SM4()
    sm4.sm4_setkey_enc(ctx, secretKey)
    val encrypted: ByteArray = sm4.sm4_crypt_cbc(ctx, iv, data)
    return encrypted

}

fun Security.decryptSM4_CBC(cipherData:ByteArray,secretKey: ByteArray,iv:ByteArray): ByteArray{
    val ctx = SM4_Context()
    ctx.isPadding = true
    ctx.mode = Sm4Model.SM4_DECRYPT

    val sm4: SM4 = SM4()
    sm4.sm4_setkey_dec(ctx, secretKey)
    val decrypted: ByteArray = sm4.sm4_crypt_cbc(ctx, iv, cipherData)
    return decrypted

}